package com.ly.ql.Wms.Service.Impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ly.ql.RocketMqListener.Produce.ProduceUtils;
import com.ly.ql.Wms.Bill.InStockBill;
import com.ly.ql.Wms.Entity.InStockDetailEntity;
import com.ly.ql.Wms.Entity.InStockHeadEntity;
import com.ly.ql.Wms.Mapper.InStockBillMapper;
import com.ly.ql.Wms.Result.InStockBillPushResult;
import com.ly.ql.Wms.Service.InStockBillPushService;
import com.ly.ql.Wms.utils.IdGenerate;
import com.ly.ql.Wms.utils.LoginUtils;
import com.ly.ql.Wms.utils.RequestK3Utils;
import com.ly.ql.Wms.utils.TypeSafeUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
public class InStockBillPushServiceImpl extends ServiceImpl<InStockBillMapper,InStockBillPushResult>implements InStockBillPushService {

    @Value(value = "${k3.PUSHURL}")
    private String k3PushUrl;

    @Value(value = "${k3.PullUrl}")
    private String k3PullUrl;

    @Value(value = "${k3.SaveUrl}")
    private String K3SaveUrl;

    @Value(value = "${k3.k3SubmitUrl}")
    private String k3SubmitUrl;

    @Value(value = "${k3.k3AuditUrl}")
    private String k3AuditUrl;
    private final InStockBillMapper inStockBillMapper;

    private final ProduceUtils produceUtils;

    private final LoginUtils loginUtils;
    /**
     * 调拨出库批量手动下推金蝶分步式调拨入库单
     * @return
     */
    @Override
    public void pushTransferIn() {
        List<InStockBillPushResult> inStockBillPushResults = inStockBillMapper.SelectPushTransInData();
        if (inStockBillPushResults!=null&&!inStockBillPushResults.isEmpty()){
            Map<String,Map<String,Object>> map=new HashMap<>();
             //整理请求数据
            for (InStockBillPushResult inStockBillPushResult : inStockBillPushResults) {
                String key=inStockBillPushResult.getOID() + inStockBillPushResult.getErpNo()+"";
                if (map.containsKey(key)){
                    HashMap<String,Object> temMap= new HashMap<>();
                    temMap.put("QTY",inStockBillPushResult.getQTY());
                    temMap.put("wareHouseCode",inStockBillPushResult.getWareHouseCode());
                    temMap.put("ErpDetailId",inStockBillPushResult.getErpDetailId());
                    List details=(ArrayList)map.get(key).get("details");
                    details.add(temMap);
                }else {
                    HashMap<String,Object> temMap= new HashMap<>();
                    temMap.put("OID",inStockBillPushResult.getOID());
                    temMap.put("ErpNo",inStockBillPushResult.getErpNo());
                    temMap.put("WareHouseCenterCode",inStockBillPushResult.getWareHouseCenterCode());
                    Map<String,Object> detail =new HashMap<>();
                    detail.put("ErpDetailId",inStockBillPushResult.getErpDetailId());
                    detail.put("QTY",inStockBillPushResult.getQTY());
                    detail.put("wareHouseCode",inStockBillPushResult.getWareHouseCode());
                    List list= new ArrayList<>();
                    list.add(detail);
                    temMap.put("details",list);
                    map.put(key,temMap);
                }
            }
            //整理数据分发请求
            for (Map.Entry<String, Map<String, Object>> stringMapEntry : map.entrySet()) {
                Map data = new LinkedHashMap();
                //CustomParams.put("",)
                Map FSTKTRSINENTRY = new LinkedHashMap();
                List<Map<String, Object>> details = (ArrayList) stringMapEntry.getValue().get("details");
                List paramList = new LinkedList();
                Map<Object, Map<String, Object>> payload = new HashMap<>();
                for (Map<String, Object> detail : details) {
                    payload.put(detail.get("ErpDetailId"), detail);
//                    Map value= new LinkedHashMap();
//                    value.put("FQty",detail.get("QTY"));
//                    Map wareHouseCode =new HashMap<>();
//                    wareHouseCode.put("FNumber",detail.get("wareHouseCode"));
//                    value.put("FDestStockID",wareHouseCode);
//                    Map erpDetail =new HashMap<>();
//                    erpDetail.put(detail.get("ErpDetailId").toString(),value);
//                    paramList.add(erpDetail);
                }
//                FSTKTRSINENTRY.put("FSTKTRSINENTRY",paramList);
//                Map Model =new HashMap<>();
//                Model.put("Model",FSTKTRSINENTRY);
                data.put("EntryIds", details.stream().map(item -> item.get("ErpDetailId").toString()).distinct().collect(Collectors.joining(",")));
                data.put("RuleId", "STK_TRANSFEROUT-STK_TRANSFERIN");
                Map TargetOrgId = new HashMap(); //组织内码，用于目标组织
                TargetOrgId.put("HT", "100146");
                TargetOrgId.put("JZX", "100134");
                TargetOrgId.put("KLLN", "100296");
                TargetOrgId.put("SKLL", "785952");
                data.put("TargetOrgId", TargetOrgId.get(stringMapEntry.getValue().get("WareHouseCenterCode")));
                // data.put("CustomParams",Model);
                Map Param = new HashMap<>();
                Param.put("formid", "STK_TRANSFEROUT");
                Param.put("data", data);

                // 循环下推金蝶
                String Number = null;
                try {
                    String Cookie = loginUtils.getLogin();
                    Map<String, String> headMap = new HashMap<>();
                    headMap.put("Cookie", Cookie);
                    String result = RequestK3Utils.sendDataByJson(k3PushUrl, JSONObject.toJSONString(Param, SerializerFeature.DisableCircularReferenceDetect), headMap);
                    if (result != null) {
                        ObjectMapper mapper = new ObjectMapper();
                        //   mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
                        Map jsonObject = (Map) ((Map) JSONObject.parseObject(result).get("Result")).get("ResponseStatus");
                        System.out.println(jsonObject);
                        if ((Boolean) jsonObject.get("IsSuccess")) {
                            Number = ((Map) ((JSONArray) jsonObject.get("SuccessEntitys")).get(0)).get("Number").toString();
                            //  PushSussesResponse pushSussesResponse =mapper.readValue(JSONArray.toJSONString(((JSONArray) jsonObject.get("SuccessEntitys")).get(0)), new TypeReference<PushSussesResponse>(){});
                            List<Object> inErpDetailIDList = (JSONArray) ((Map) ((Map) ((JSONArray) jsonObject.get("SuccessEntitys")).get(0)).get("EntryIds")).get("FSTKTRSINENTRY");
                            String collectDetails = inErpDetailIDList.stream().map(item -> item + "").collect(Collectors.joining(","));
                            //成功之后走查询+保存一起走了
                            try {
                                Map ParamSelect = new HashMap<>();
                                LinkedHashMap dataSelect = new LinkedHashMap<>();
                                dataSelect.put("FormId", "STK_TRANSFERIN");
                                dataSelect.put("FieldKeys", "FID,FSTKTRSINENTRY_FEntryID,F_PAEZ_YDFLID");
                                dataSelect.put("FilterString", "FSTKTRSINENTRY_FEntryID IN (" + collectDetails + ")");
                                ParamSelect.put("data", dataSelect);

                                String pullResult = RequestK3Utils.sendDataByJson(k3PullUrl, JSONObject.toJSONString(ParamSelect, SerializerFeature.DisableCircularReferenceDetect), headMap);
                                if (pullResult != null && !pullResult.isEmpty()) {
                                    try {
                                        Map SaveData = new HashMap<>();
                                        Map FENTITY = new LinkedHashMap<>();
                                        List FentityList = new LinkedList();
                                        JSONArray array = JSONArray.parseArray(pullResult);
                                        for (Object o : array) {
                                            if (o instanceof Map) {
                                                Map temp = (Map) o;
                                                Long key = (((Integer) temp.get("F.PAEZ.YDFLID")).longValue());
                                                if (payload.containsKey(key)) {
                                                    Map value = new LinkedHashMap();
                                                    value.put("FEntryID", temp.get("FSTKTRSINENTRY.FEntryID"));
                                                    Map wareHouseCode = new HashMap<>();
                                                    wareHouseCode.put("FNumber", payload.get(key).get("wareHouseCode"));
                                                    value.put("FDestStockID", wareHouseCode);
                                                    value.put("FQty", payload.get(key).get("QTY"));
                                                    FentityList.add(value);
                                                }
                                            }
                                        }
                                        FENTITY.put("FID", ((Map) array.get(0)).get("FID"));
                                        FENTITY.put("FSTKTRSINENTRY", FentityList);
                                        SaveData.put("IsDeleteEntry", false);
                                        SaveData.put("IgnoreInterationFlag", false);
                                        SaveData.put("Model", FENTITY);
                                        Map SaveParam = new HashMap<>();
                                        SaveParam.put("formid", "STK_TRANSFERIN");
                                        SaveParam.put("data", SaveData);
                                        System.out.println(JSONObject.toJSONString(SaveParam, SerializerFeature.DisableCircularReferenceDetect));
                                        String SaveResult = RequestK3Utils.sendDataByJson(K3SaveUrl, JSONObject.toJSONString(SaveParam, SerializerFeature.DisableCircularReferenceDetect), headMap);
                                        if (SaveResult != null && !SaveResult.isEmpty()) {
                                            Map saveResultMap = (Map) ((Map) JSONObject.parseObject(result).get("Result")).get("ResponseStatus");
                                            if ((Boolean) saveResultMap.get("IsSuccess")) {
                                                try {
                                                    //提交+审核
                                                    Map SuccessEntity = (Map) ((JSONArray) saveResultMap.get("SuccessEntitys")).get(0);
                                                    Map dataSubmit = new HashMap();
                                                    dataSubmit.put("Ids", SuccessEntity.get("Id"));
                                                    Map submitParam = new HashMap<>();
                                                    submitParam.put("formid", "STK_TRANSFERIN");
                                                    submitParam.put("data", dataSubmit);

                                                    String submitResult = RequestK3Utils.sendDataByJson(k3SubmitUrl, JSONObject.toJSONString(submitParam, SerializerFeature.DisableCircularReferenceDetect), headMap);
                                                    System.out.println(submitResult);
                                                    if (submitResult != null && !submitResult.isEmpty()) {
                                                        Map submitResultMap = (Map) ((Map) JSONObject.parseObject(result).get("Result")).get("ResponseStatus");
                                                        if ((Boolean) submitResultMap.get("IsSuccess")) {
                                                            //审核
                                                            Map dataAudit = new HashMap<>();
                                                            dataAudit.put("Ids", SuccessEntity.get("Id"));
                                                            Map AuditParam = new HashMap<>();
                                                            AuditParam.put("data", dataAudit);
                                                            AuditParam.put("formid", "STK_TRANSFERIN");
                                                            String AuditResult = RequestK3Utils.sendDataByJson(k3AuditUrl, JSONObject.toJSONString(AuditParam, SerializerFeature.DisableCircularReferenceDetect), headMap);
                                                            if (AuditResult != null && !AuditResult.isEmpty()) {
                                                                Map AuditResultMap = (Map) ((Map) JSONObject.parseObject(result).get("Result")).get("ResponseStatus");
                                                                if ((Boolean) AuditResultMap.get("IsSuccess")) {
                                                                    //审核成功 记录审核状态
                                                                    Object OID = stringMapEntry.getValue().get("OID");
                                                                    inStockBillMapper.UpdateBIllSatusByOId("lrp_inboundnotice_h", (Long) OID);
                                                                } else {
                                                                    throw new Exception("金蝶单号为" + Number + "审核失败" + AuditResult);
                                                                }
                                                            }
                                                        } else {
                                                            throw new Exception("金蝶单号为" + Number + "提交失败" + submitResult);
                                                        }
                                                    }
                                                } catch (Exception e) {
                                                    throw new Exception("提交或者审核请求失败,金蝶调拨入库单号为:" + Number + " 异常为" + e.getMessage());
                                                }
                                            }
                                        } else {
                                            throw new Exception("保存无响应 金蝶调拨入库单号为" + Number + "异常为" + SaveResult);
                                        }
                                    } catch (Exception e) {
                                        throw new Exception("下推后保存失败" + e.getMessage());
                                    }
                                } else {
                                    throw new Exception("下推分步式调拨入库查询无响应");
                                }
                            } catch (Exception e) {
                                //如果包含 分步式调出单“调出数量”大于“入库关联数量”与“途损关联数量”之和 已经下推
                                throw new Exception("下推后查询单据失败" + e.getMessage());
                            }
                            System.out.println(inErpDetailIDList);
                        } else {
                            Map SuccessEntity =  ((Map) ((JSONArray) jsonObject.get("Errors")).get(0));
                            if (SuccessEntity.get("Message").toString().contains("分步式调出单“调出数量”大于“入库关联数量”与“途损关联数量”之和才能下推")){
                                Object OID = stringMapEntry.getValue().get("OID");
                                inStockBillMapper.UpdateBIllSatusByOId("lrp_inboundnotice_h", (Long) OID);
                            }else {
                                throw new Exception("下推失败:" + result);
                            }
                        }
                    }
                } catch (Exception e) {
                        //异常项推送MQ 发送邮件 (统一异常处理)
                        Map HeadMap = new HashMap<>();
                        if (Number != null) {
                            HeadMap.put("key", Number);
                        } else {
                            HeadMap.put("key", stringMapEntry.getValue().get("ErpNo"));
                        }
                        produceUtils.sendMessageOrder(e.getMessage(), HeadMap, (Long) stringMapEntry.getValue().get("OID"));
                }
            }
        }
    }
    @Override
    public void InsertBill(String ErpNo,String FormId) {
        Map ParamSelect = new HashMap<>();
        LinkedHashMap dataSelect = new LinkedHashMap<>();
        if ("PUR_ReceiveBill".equals(FormId)){
            dataSelect.put("FormId",FormId);
            dataSelect.put("FieldKeys", "FDemandOrgId.FNumber,FDate,FSupplierId.FNumber,FNote,FDetailEntity_FEntryID,FMaterialId.FNumber,FMateriaModel,FLot.FNumber,F_abc_ZBQSL,FUnitId.FNumber,F_PAEZ_Edition,F_abc_LONGDU,FActReceiveQty,FID,FOrderBillNo,FMaterialId.F_abc_POTFLG,FMaterialId.F_PAEZ_EnableVersion,FCheckInComing,Fbillno,F_PAEZ_BBWLMC,F_PAEZ_BBWLGGXH,FStockOrgId.FNumber,FStockID.FNumber,F_PAEZ_WMSCW.FNumber,FDescription,FOrderBillNo,FDetailEntity_FSEQ");
            dataSelect.put("FilterString", "FBillNo IN ('') OR (FStockOrgId.FNumber IN ('JZX','HT','KLLN','SKLL') and (LEFT(FMaterialId.FNumber,2) IN ('51') OR LEFT(FMaterialId.FNumber,1) IN ('4','3')) AND (F_PAEZ_TJTIME>='2024-09-22 10:39:46' AND F_PAEZ_TJTIME <= '2024-10-15 08:52:16') AND FDocumentStatus ='C')");
            ParamSelect.put("data", dataSelect);
        }
        try {
            String Cookie = loginUtils.getLogin();
            Map<String, String> headMap = new HashMap<>();
            headMap.put("Cookie", Cookie);
            String pullResult = RequestK3Utils.sendDataByJson(k3PullUrl, JSONObject.toJSONString(ParamSelect, SerializerFeature.DisableCircularReferenceDetect), headMap);
            JSONArray Result = JSONArray.parseArray(pullResult);
            LinkedList<InStockBill> listInStockBill =new LinkedList<>();
            Map<String,InStockBill> inStockBillMap =new LinkedHashMap<>();
            if (Result.size()>0){
                if ("PUR_ReceiveBill".equals(FormId)){
                    //写入表单(需要先根据查询来的数据进行分组)
                    for (Object o : Result) {
                        Map<String,Object> map= (Map<String, Object>) o;
                        String key =TypeSafeUtils.TypeToString(map.get("Fbillno"))+map.get("FID")+map.get("FDemandOrgId.FNumber")+"";
                        InStockDetailEntity detailEntity = new InStockDetailEntity();
                        detailEntity.setOID(IdGenerate.newOID());
                        detailEntity.setCREATOR(loginUtils.getUserId());
                        detailEntity.setErpDetailId(TypeSafeUtils.typeToLong(map.get("FDetailEntity.FEntryID")));
                        detailEntity.setBasicQty(TypeSafeUtils.typeToDecimal(map.get("F.abc.ZBQSL")));
                        detailEntity.setBatchNo(TypeSafeUtils.TypeToString(map.get("FLot.FNumber")));
                        detailEntity.setConcentration((Boolean)map.get("FMaterialId.F.abc.POTFLG")==false?new BigDecimal(100.00): TypeSafeUtils.typeToDecimal(map.get("F.abc.LONGDU")));
                        detailEntity.setIsReceiveQc((Boolean) map.get("FCheckInComing")==true ? 1:0);
                        detailEntity.setQty(detailEntity.getBasicQty());
                        detailEntity.setDiscountQty((Boolean)map.get("FMaterialId.F.abc.POTFLG")==false?detailEntity.getBasicQty():detailEntity.getBasicQty().multiply(detailEntity.getConcentration().divide(new BigDecimal(100)).setScale(12, RoundingMode.HALF_UP)).setScale(6,RoundingMode.HALF_UP));
                        detailEntity.setVersionCode((Boolean)map.get("FMaterialId.F.PAEZ.EnableVersion")==false?"*":TypeSafeUtils.TypeToString(map.get("F.PAEZ.Edition")));
                        detailEntity.setSpec(TypeSafeUtils.TypeToString(map.get("FMateriaModel")));
                        HashMap condition= new HashMap<>();
                        condition.put("Code",map.get("FUnitId.FNumber"));
                        detailEntity.setMaterialUnit(TypeSafeUtils.TypeToString(baseMapper.selectNameByCondition("LRP_MaterialUnit",condition).get("name")));
                        condition.put("Code",map.get("FStockOrgId.FNumber").toString()+"|"+map.get("FMaterialId.FNumber"));
                        detailEntity.setMaterialId(baseMapper.selectIdByCondition("lrp_material",condition));
                        condition.put("Code",map.get("FStockOrgId.FNumber").toString()+"|"+map.get("FStockID.FNumber"));
                        detailEntity.setStoreroomId(baseMapper.selectIdByCondition("lrp_storeroom",condition));
                        condition.put("Code",map.get("FStockOrgId.FNumber").toString()+"|"+map.get("F.PAEZ.WMSCW.FNumber"));
                        detailEntity.setLocationId(baseMapper.selectIdByCondition("lrp_location",condition));
                        detailEntity.setVersionName(TypeSafeUtils.TypeToString(map.get("F.PAEZ.BBWLMC")));
                        detailEntity.setVersionMode(TypeSafeUtils.TypeToString(map.get("F.PAEZ.BBWLGGXH")));
                        detailEntity.setERPLineID(TypeSafeUtils.typeToInteger(map.get("FDetailEntity.FSEQ")));
                        if (inStockBillMap.containsKey(key)){
                            detailEntity.setSOID(inStockBillMap.get(key).getInStockHeadEntity().getSOID());
                            inStockBillMap.get(key).getInStockDetailEntity().add(detailEntity);
                        }else {
                            InStockHeadEntity headEntity=new InStockHeadEntity();
                            headEntity.setOID(IdGenerate.newOID());
                            condition.put("Code",TypeSafeUtils.TypeToString(map.get("FStockOrgId.FNumber")));
                            headEntity.setWarehouseCenterId(inStockBillMapper.selectIdByCondition("lrp_warehousecenter", condition));
                            headEntity.setFormId(FormId);
                            headEntity.setIsReceiveQc((Boolean) map.get("FCheckInComing")==true ? 1:0);
                            headEntity.setErpHeadId(TypeSafeUtils.typeToLong(map.get("FID")));
                            headEntity.setCREATOR(loginUtils.getUserId());
                            headEntity.setOwnerNo(TypeSafeUtils.TypeToString(map.get("Fbillno")));
                            headEntity.setExpectDateTimeFrom(LocalDateTime.parse(TypeSafeUtils.TypeToString(map.get("FDate")),DateTimeFormatter.ISO_LOCAL_DATE_TIME));
                            detailEntity.setSOID(headEntity.getOID());
                            InStockBill inStockBill =new InStockBill();

                            inStockBill.setInStockHeadEntity(headEntity);
                            LinkedList<InStockDetailEntity> InStockDetailList =new LinkedList<>();
                            InStockDetailList.add(detailEntity);
                            inStockBill.setInStockDetailEntity(InStockDetailList);
                            inStockBillMap.put(key,inStockBill);
                        }
                    }
                    inStockBillMap.entrySet().forEach(Entity->{
                        // 表单集合 循环插入或更新数据库(状态大于200 则 去除)

                        InStockBill bill = Entity.getValue();
                        HashMap condition= new HashMap<>();
                        condition.put("ErpHeadId",bill.getInStockHeadEntity().getErpHeadId());
                        condition.put("OwnerNo",bill.getInStockHeadEntity().getOwnerNo());
                        condition.put("OwnerId",bill.getInStockHeadEntity().getErpHeadId());
                        Integer Status = TypeSafeUtils.typeToInteger(inStockBillMapper.selectNameByCondition("LRP_MaterialUnit", condition).get("Status"));
                        try {
                            if (Status>0&&Status<=200){ //执行插入

                            }
                        }catch (Exception e){
                           throw new RuntimeException("单据保存失败，金蝶单号为："+bill.getInStockHeadEntity().getOwnerNo()+"异常为："+e.getMessage());
                        }
                    });

                }
            }else if (Result.size()==0){
               //打印请求日志 写入日志框架
            }
        }catch (Exception e){
             //推送MQ处理 发送邮件

            System.out.println(e.getMessage());
        }
    }
}
